﻿
using System.Collections.Concurrent;
using TrackSystem.Contracts;
using TrackSystem.Entities.Dtos.Sensor;
using TrackSystem.Entities.Extensions;
using TrackSystem.IO.Equip;
using TrackSystem.IO.Formula;
using TrackSystem.IO.Models;
using TrackSystem.IO.Ports;
using TrackSystem.IO.Protocol;
using TrackSystem.IO.Utils;

namespace TrackSystem.IO.Sensors
{
    /// <summary>
    /// 传感器管理类
    /// </summary>
    public class SensorFactory
    {
        public static SensorFactory Instance;

        /// <summary>
        /// 传感器列表
        /// </summary>
        public ConcurrentDictionary<string, ProtocolBase> Items;
        /// <summary>
        /// 传感器名称和序号对照表
        /// </summary>
        public ConcurrentDictionary<int, string> IdNameDictionary;

        /// <summary>
        /// 构造函数
        /// </summary>
        static SensorFactory()
        {
            Instance = new SensorFactory();
            Instance.Initialize();
        }

        /// <summary>
        /// 初始化函数
        /// </summary>
        private void Initialize()
        {
            Items = new();
            IdNameDictionary = new();
        }

        /// <summary>
        /// 载入传感器数据
        /// </summary>
        /// <param name="wrapper"></param>
        /// <returns></returns>
        public async Task<ResultMsg> Load(IRepositoryWrapper wrapper)
        {
            try
            {
                var sensors = await wrapper.Sensor.GetAllWithChannelAsync();
                sensors = sensors.OrderBy(a => a.Id);

                // 首先释放端口所有资源
                Unload();

                foreach (var snr in sensors)
                {
                    switch (snr.Channel.Protocol)
                    {
                        // modbus协议
                        case ProtocolEnum.Modbus:
                            ModbusProtocol mdSensor = new ModbusProtocol(
                                snr.Name,
                                snr.Station, snr.RO_Address, snr.RO_Length,
                                snr.RW_Address, snr.RW_Length);
                            if (snr.Channel.optSplit3_4Cmd)
                                mdSensor.Enable_Splite3_4();
                            mdSensor.optSupport21Cmd = snr.Channel.optSupport21Cmd;
                            Items.TryAdd(snr.Name, mdSensor);
                            PortFactory.Instance.Insert(snr.Channel, mdSensor);
                            break;

                        // 电源板协议
                        case ProtocolEnum.Power:
                            PowerProtocol pwSensor = new PowerProtocol(snr.Name, snr.Station);
                            Items.TryAdd(snr.Name, pwSensor);
                            PortFactory.Instance.Insert(snr.Channel, pwSensor);
                            break;

                        // 高度计协议 PA500
                        case ProtocolEnum.Altimeter:
                            AltimeterProtocol alSensor = new AltimeterProtocol(snr.Name);
                            Items.TryAdd(snr.Name, alSensor);
                            PortFactory.Instance.Insert(snr.Channel, alSensor);
                            break;

                        // 高度计协议 ISA500
                        case ProtocolEnum.ISA500:
                            ISA500Protocol altimeterSensor = new ISA500Protocol(snr.Name);
                            Items.TryAdd(snr.Name, altimeterSensor);
                            PortFactory.Instance.Insert(snr.Channel, altimeterSensor);
                            break;

                        // 国产高度计协议 HDC-S200
                        case ProtocolEnum.HDCS200:
                            HDCS200Protocol altiSensor = new HDCS200Protocol(snr.Name);
                            Items.TryAdd(snr.Name, altiSensor);
                            PortFactory.Instance.Insert(snr.Channel, altiSensor);
                            break;

                        // 深度计协议
                        case ProtocolEnum.Depth:
                            DeptherProtocol dpSensor = new DeptherProtocol(snr.Name);
                            Items.TryAdd(snr.Name, dpSensor);
                            PortFactory.Instance.Insert(snr.Channel, dpSensor);
                            break;

                        // 探索二号罗经协议
                        case ProtocolEnum.Ship2_gyro:
                            Ship2GyroProtocol gyroSensor = new Ship2GyroProtocol(snr.Name);
                            Items.TryAdd(snr.Name, gyroSensor);
                            PortFactory.Instance.Insert(snr.Channel, gyroSensor);
                            break;

                        // 姿态传感器协议（SCM系列）
                        case ProtocolEnum.Compass:
                            CompassProtocl CompassSensor = new CompassProtocl(snr.Name, snr.RO_Length, snr.RW_Length);
                            Items.TryAdd(snr.Name, CompassSensor);
                            PortFactory.Instance.Insert(snr.Channel, CompassSensor);
                            break;

                        // 姿态传感器协议（SCM340）
                        case ProtocolEnum.Compass3D:
                            Compass3DProtocl Compass3DSensor = new Compass3DProtocl(snr.Name, snr.RO_Length, snr.RW_Length);
                            Items.TryAdd(snr.Name, Compass3DSensor);
                            PortFactory.Instance.Insert(snr.Channel, Compass3DSensor);
                            break;

                        // 姿态传感器协议
                        case ProtocolEnum.LEC210:
                            LEC210Protocl LEC210Sensor = new LEC210Protocl(snr.Name, snr.RO_Length, snr.RW_Length);
                            Items.TryAdd(snr.Name, LEC210Sensor);
                            PortFactory.Instance.Insert(snr.Channel, LEC210Sensor);
                            break;

                        // 网络摄像头串口协议
                        case ProtocolEnum.Camera:
                            CameraProtocl CameraSensor = new CameraProtocl(snr.Name, snr.RO_Length, snr.RW_Length);
                            Items.TryAdd(snr.Name, CameraSensor);
                            PortFactory.Instance.Insert(snr.Channel, CameraSensor);
                            break;

                        // 网络摄像头协议
                        case ProtocolEnum.NetCameraTCP:
                            NetCameraTCPProtocl NetCameraSensor = new NetCameraTCPProtocl(snr.Name, snr.Channel.Ip, snr.Channel.Port, "admin", "idsse401", snr.RO_Length, snr.RW_Length);
                            Items.TryAdd(snr.Name, NetCameraSensor);
                            PortFactory.Instance.Insert(snr.Channel, NetCameraSensor);
                            break;

                        // 绝缘检测协议
                        case ProtocolEnum.Insulation:
                            InsulatProtocol insulatProtocol = new InsulatProtocol(snr.Name, snr.Station);
                            Items.TryAdd(snr.Name, insulatProtocol);
                            PortFactory.Instance.Insert(snr.Channel, insulatProtocol);
                            break;

                        // 惯导
                        case ProtocolEnum.INS:
                            HskINSProtocol hskIns = new HskINSProtocol(snr.Name);
                            Items.TryAdd(snr.Name, hskIns);
                            PortFactory.Instance.Insert(snr.Channel, hskIns);
                            break;

                        // SDI OSD叠加
                        case ProtocolEnum.SDI_OSD:
                            SDIOSDProtocol sdiOSD = new SDIOSDProtocol(snr.Name, snr.RO_Length, snr.RW_Length);
                            Items.TryAdd(snr.Name, sdiOSD);
                            PortFactory.Instance.Insert(snr.Channel, sdiOSD);
                            break;

                        // 探索二号GPS信息
                        case ProtocolEnum.Ship2_GPS:
                            Ship2GPSProtocol ship2GPS = new Ship2GPSProtocol(snr.Name);
                            Items.TryAdd(snr.Name, ship2GPS);
                            PortFactory.Instance.Insert(snr.Channel, ship2GPS);
                            break;

                        // 探索二号USBL信息
                        case ProtocolEnum.Ship2_USBL:
                            Ship2USBLProtocol ship2USBL = new Ship2USBLProtocol(snr.Name);
                            Items.TryAdd(snr.Name, ship2USBL);
                            PortFactory.Instance.Insert(snr.Channel, ship2USBL);
                            break;

                        // GPVTG地面速度信息
                        case ProtocolEnum.Ship2_GPVTG:
                            Ship2GPVTGProtocol ship2GPVTG = new Ship2GPVTGProtocol(snr.Name);
                            Items.TryAdd(snr.Name, ship2GPVTG);
                            PortFactory.Instance.Insert(snr.Channel, ship2GPVTG);
                            break;

                        // 深拖的GPS信息
                        case ProtocolEnum.DTGPS:
                            DTGPSProtocol DTGPS = new DTGPSProtocol(snr.Name);
                            Items.TryAdd(snr.Name, DTGPS);
                            PortFactory.Instance.Insert(snr.Channel, DTGPS);
                            break;

                        // PTZ网络相机控制
                        case ProtocolEnum.PTZCam:
                            PTZCamProtocol ptzCam = new PTZCamProtocol(snr.Name, snr.Channel.Ip, snr.Channel.Port);
                            Items.TryAdd(snr.Name, ptzCam);
                            PortFactory.Instance.Insert(snr.Channel, ptzCam);
                            break;

                        // modbus只读功能协议
                        case ProtocolEnum.ModbusReadOnly:
                            ModbusReadOnlyProtocol mdROSensor = new ModbusReadOnlyProtocol(snr.Name, snr.Station, snr.RO_Address, snr.RO_Length);
                            Items.TryAdd(snr.Name, mdROSensor);
                            PortFactory.Instance.Insert(snr.Channel, mdROSensor);
                            break;

                        // DVL数据读取功能协议
                        case ProtocolEnum.DVL:
                            DVLProtocol dvlSensor = new DVLProtocol(snr.Name);
                            Items.TryAdd(snr.Name, dvlSensor);
                            PortFactory.Instance.Insert(snr.Channel, dvlSensor);
                            break;

                        // 绞车A架状态读取功能协议
                        case ProtocolEnum.Winch:
                            WinchProtocol winchSensor = new WinchProtocol(snr.Name);
                            Items.TryAdd(snr.Name, winchSensor);
                            PortFactory.Instance.Insert(snr.Channel, winchSensor);
                            break;

                        // 招商采矿车支持母船罗经读取功能协议
                        case ProtocolEnum.CMI_Gyro:
                            CMIGyroProtocol cmi_gyroSensor = new CMIGyroProtocol(snr.Name);
                            Items.TryAdd(snr.Name, cmi_gyroSensor);
                            PortFactory.Instance.Insert(snr.Channel, cmi_gyroSensor);
                            break;

                        // 招商采矿车支持母船罗经读取功能协议
                        case ProtocolEnum.CMI_USBL:
                            USBLProtocol cmi_usblSensor = new USBLProtocol(snr.Name);
                            Items.TryAdd(snr.Name, cmi_usblSensor);
                            PortFactory.Instance.Insert(snr.Channel, cmi_usblSensor);
                            break;

                        // 招商采矿车支持母船罗经读取功能协议
                        case ProtocolEnum.CMI_LBL:
                            LBLProtocol cmi_lblSensor = new LBLProtocol(snr.Name);
                            Items.TryAdd(snr.Name, cmi_lblSensor);
                            PortFactory.Instance.Insert(snr.Channel, cmi_lblSensor);
                            break;

                        // ROV Brow 4K相机（张兵）
                        case ProtocolEnum.CAM4K:
                            Camera4KProtocol cam_4K = new Camera4KProtocol(snr.Name);
                            Items.TryAdd(snr.Name, cam_4K);
                            PortFactory.Instance.Insert(snr.Channel, cam_4K);
                            break;

                        // LLC S7-1200
                        case ProtocolEnum.PLC_S71200:
                            PLCS71200Protocol plc = new PLCS71200Protocol(snr.Name, snr.Channel.Ip, snr.Station, snr.RO_Address, snr.RO_Length,
                                snr.RW_Address, snr.RW_Length);
                            Items.TryAdd(snr.Name, plc);
                            PortFactory.Instance.Insert(snr.Channel, plc);
                            break;

                        // Seapath 42 信息
                        case ProtocolEnum.Seapath_42:
                            Seapath42Protocol seapath42 = new Seapath42Protocol(snr.Name);
                            Items.TryAdd(snr.Name, seapath42);
                            PortFactory.Instance.Insert(snr.Channel, seapath42);
                            break;

                        // MODBUS-TCP协议
                        case ProtocolEnum.ModbusTCP:
                            ModbusTCPPtl mdTcp = new ModbusTCPPtl(snr.Name, snr.Station, 
                                snr.RO_Address, snr.RO_Length, snr.RW_Address, snr.RW_Length);
                            Items.TryAdd(snr.Name, mdTcp);
                            PortFactory.Instance.Insert(snr.Channel, mdTcp);
                            break;

                        // 缺省情况下，采用MODBUS协议
                        default:
                            ModbusProtocol other = new ModbusProtocol(
                                snr.Name,
                                snr.Station, snr.RO_Address, snr.RO_Length,
                                snr.RW_Address, snr.RW_Length);

                            Items.TryAdd(snr.Name, other);
                            PortFactory.Instance.Insert(snr.Channel, other);
                            break;
                    }

                    var regs = await wrapper.Var.GetSensorRegsAsync(snr.Id);
                    Items[snr.Name].RegNameList = regs.Select(x => x.Name).ToList();
                    Items[snr.Name].Enabled = snr.Eabled;
                    Items[snr.Name].EquipId = snr.equipId;
                    IdNameDictionary.TryAdd(snr.Id, snr.Name);

                    if (EquipFactory.Instance.TryGetValue(snr.equipId, out EquipItem? equipItem))
                    {
                        equipItem?.TryAddSensor(Items[snr.Name]);
                    }
                }

                return ResultMsg.Succ("初始化传感器成功");
            }
            catch (Exception ex)
            {
                return ResultMsg.Fail($"传感器初始化错误，{ex.Message}");
            }
        }

        /// <summary>
        /// 卸载所有传感器
        /// </summary>
        public void Unload()
        {
            PortFactory.Instance.Disposable();
            foreach (var item in Items.Values)
            {
                if (EquipFactory.Instance.TryGetValue(item.EquipId, out var equip))
                {
                    equip?.Parts?.TryRemove(item.Name, out var _);
                }
            }
            Items.Clear();
            IdNameDictionary.Clear();
        }
    }
}
